package com.jacklei.ch14;

import java.util.*;

/*
* 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行，并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间，CPU 可以完成一个任务，或者处于待命状态。

然而，两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间，因此至少有连续 n 个单位时间内 CPU 在执行不同的任务，或者在待命状态。

你需要计算完成所有任务所需要的 最短时间 。

 

示例 1：

输入：tasks = ["A","A","A","B","B","B"], n = 2
输出：8
解释：A -> B -> (待命) -> A -> B -> (待命) -> A -> B
     在本示例中，两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间，而执行一个任务只需要一个单位时间，所以中间出现了（待命）状态。
示例 2：

输入：tasks = ["A","A","A","B","B","B"], n = 0
输出：6
解释：在这种情况下，任何大小为 6 的排列都可以满足要求，因为 n = 0
["A","A","A","B","B","B"]
["A","B","A","B","A","B"]
["B","B","B","A","A","A"]
...
诸如此类
示例 3：

输入：tasks = ["A","A","A","A","A","A","B","C","D","E","F","G"], n = 2
输出：16
解释：一种可能的解决方案是：
     A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> (待命) -> (待命) -> A -> (待命) -> (待命) -> A
 

提示：

1 <= task.length <= 104
tasks[i] 是大写英文字母
n 的取值范围为 [0, 100]

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/task-scheduler
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。*/
public class TaskScheduler {
    public static void main(String[] args) {
        TaskScheduler t = new TaskScheduler();
        System.out.println(t.leastInterval(new char[]{'A', 'A', 'A', 'B', 'B', 'B'}, 2));
    }
    //使用队列
    public int leastInterval(char[] tasks, int n) {
        if(n == 0) return tasks.length;
        int res = 0;
        Queue<Map.Entry<Character,Integer>> queue = new LinkedList<>();//队列
        HashMap <Character,Integer> map= new  HashMap();//hashmap
        PriorityQueue<Map.Entry<Character,Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Character, Integer>>() {
            @Override
            public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
                return o2.getValue() - o1.getValue();
            }
        });//大根堆
        for (char task : tasks) {
            map.put(task, map.getOrDefault(task,0)+1);
        }

        for (Map.Entry<Character,Integer> entry : map.entrySet()) {
            pq.offer(entry);
        }
        int end = 0;
        while (!pq.isEmpty()){
            //进队列
            end =0;
            for (int i =0 ; i <= n; i++){
                if (!pq.isEmpty()) {
                    Map.Entry<Character, Integer> poll = pq.poll();
                    queue.add(poll);
                    end++;
                }
            }
            res += n+1;
            //出队列
            while(!queue.isEmpty()){
                Map.Entry<Character, Integer> poll = queue.poll();
                if(poll.getValue() > 1) {
                    poll.setValue(poll.getValue()-1);
                    pq.offer(poll);
                }
            }
        }
        return  res - (n+1) + end;
    }
}
